﻿using CIS.DB;
using CIS.Web.Common;
using CIS.Web.Models;
using CIS.Web.Properties;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using System.Web.Mvc;
using static System.Net.Mime.MediaTypeNames;

namespace CIS.Web.Controllers
{
	[RoutePrefix("SysInvoice")]
	public class SysInvoiceController : BaseDbController
	{
		private string _importMessage;

		public ActionResult Index()
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			return View();
		}

		public async Task<JsonCamelCaseResult> GetData(int? page, int? rows, string sort, string order, InvoiceModel model)
		{
			int take = rows ?? ConstValues.DefaultGridRows;
			int skip = ((page ?? 1) - 1) * take;

			var sql = DbContext.InvoiceMaster.AsNoTracking().Where(x => !string.IsNullOrEmpty(x.Status));
			if (!string.IsNullOrWhiteSpace(model.SelTaxNum))
			{
				sql = sql.Where(x => x.InvoiceTitle.Contains(model.SelTaxNum) || x.TaxNum.Contains(model.SelTaxNum));
			}
			int total = await sql.CountAsync();
			if (!string.IsNullOrEmpty(sort))
			{
				sql = sql.OrderBy(sort + ConstValues.chrSpace + order).Skip(skip).Take(take);
			}
			else
			{
				sql = sql.OrderBy(x => x.InvoiceTitle).ThenBy(x => x.CreateDate).Skip(skip).Take(take);
			}

			var sqlResult = await sql.ToListAsync();
			var result = sqlResult.Select(x => new
			{
				ID = x.ID,
				InvoiceTitle = x.InvoiceTitle,
				TaxNum = x.TaxNum,
				AddressAndTel = x.AddressAndTel,
				Bank = x.Bank,
				BankAccount = x.BankAccount,
				Status = x.Status,
				Sort = x.Sort,
				Remark = x.Remark,
				CreateDate = LoginUser.Language == ConstValues.Language.Cn ? x.CreateDate.Value.ToString("yyyy-MM-dd") : x.CreateDate.Value.ToString("MM/dd/yyyy"),
				CreateIP = x.CreateIP,
				Creator = x.Creator
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		public async Task<JsonCamelCaseResult> GetEditData(string id)
		{
			var result = await DbContext.InvoiceMaster.AsNoTracking().FirstOrDefaultAsync(x => x.ID == id);

			if (result != null)
			{
				return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<JsonResult> Create(InvoiceModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.InvoiceMaster
				    .FirstOrDefaultAsync(x => x.InvoiceTitle == model.InvoiceTitle);
			if (result != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
					string.Format(Resources.MsgRecordExist, Resources.InvoiceTitle)),
					JsonRequestBehavior.AllowGet);
			}

			var invoiceMaster = new InvoiceMaster
			{
				ID = Utility.GetTableId(ConstValues.TableName.InvoiceMaster),
				InvoiceTitle = model.InvoiceTitle?.Trim(),
				TaxNum = !string.IsNullOrWhiteSpace(model.TaxNum) ? model.TaxNum?.Trim() : ConstValues.DefaultInvoice,
				AddressAndTel = model.AddressAndTel?.Trim(),
				Bank = model.Bank?.Trim(),
				BankAccount = model.BankAccount?.Trim(),

				Status = model.Status,
				Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort,
				Remark = model.Remark?.Trim(),
				Creator = LoginUser.UserName,
				CreateIP = LoginUser.IP,
				CreateDate = DateTime.Now
			};

			DbContext.InvoiceMaster.Add(invoiceMaster);
			await DbContext.SaveChangesAsync();

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<JsonResult> Modify(InvoiceModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var exist = await DbContext.InvoiceMaster
					.FirstOrDefaultAsync(x => x.ID != model.Id &&
						x.InvoiceTitle == model.InvoiceTitle &&
						x.TaxNum == model.TaxNum);

			if (exist != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
						string.Format(Resources.MsgRecordExist, Resources.InvoiceTitle)),
						JsonRequestBehavior.AllowGet);
			}

			var result = await DbContext.InvoiceMaster
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result != null)
			{
				result.InvoiceTitle = model.InvoiceTitle?.Trim();
				result.TaxNum = !string.IsNullOrWhiteSpace(model.TaxNum) ? model.TaxNum?.Trim() : ConstValues.DefaultInvoice;
				result.AddressAndTel = model.AddressAndTel?.Trim();
				result.Bank = model.Bank?.Trim();
				result.BankAccount = model.BankAccount?.Trim();
				result.Status = model.Status;
				result.Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort;
				result.Remark = model.Remark?.Trim();
				result.Updater = LoginUser.UserName;
				result.UpdateIP = LoginUser.IP;
				result.UpdateDate = DateTime.Now;

				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<JsonResult> Delete(InvoiceModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.InvoiceMaster
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result != null)
			{
				DbContext.InvoiceMaster.Remove(result);
				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<FileResult> Export(string allId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var ids = allId.Split(ConstValues.chrComma);

			var export = Resources.import_invoiceInfo;

			XSSFWorkbook workbook;

			using (MemoryStream readStream = new MemoryStream(export))
			{
				workbook = new XSSFWorkbook(readStream);
				ISheet sheet = workbook.GetSheetAt(0);

				ICell cell = sheet.GetRow(0).CreateCell(5);
				cell.SetCellValue("录入时间");

				var result = await DbContext.InvoiceMaster.AsNoTracking()
						.Where(x => ids.Contains(x.ID.ToString()))
						.OrderBy(x => x.InvoiceTitle).ThenBy(x => x.CreateDate)
						.ToListAsync();

				var count = 0;
				foreach (var model in result)
				{
					count += 1;
					IRow row = sheet.CreateRow(count);

					// 发票抬头
					int column = 0;
					cell = row.CreateCell(column);
					cell.SetCellValue(model.InvoiceTitle);

					// 纳税人识别号
					column++;
					cell = row.CreateCell(column);
					cell.SetCellValue(model.TaxNum);

					// 地址及电话
					column++;
					cell = row.CreateCell(column);
					cell.SetCellValue(model.AddressAndTel);

					// 开户行
					column++;
					cell = row.CreateCell(column);
					cell.SetCellValue(model.Bank);

					// 银行账号
					column++;
					cell = row.CreateCell(column);
					cell.SetCellValue(model.BankAccount);

					// 录入时间
					column++;
					cell = row.CreateCell(column);
					cell.SetCellValue(model.CreateDate.Value.ToString("yyyy-MM-dd"));
				}
			}

			MemoryStream exportStream = new MemoryStream();
			workbook.Write(exportStream);
			exportStream.Flush();
			exportStream.Position = 0;

			return File(exportStream, Application.Octet,
					$"export_invoiceInfo_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx");
		}

		public ActionResult DownloadImportTemplate()
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			return File(Resources.import_invoiceInfo,
					"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
					$"import_invoiceInfo.xlsx");
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<JsonResult> Import(InvoiceModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			if (model.ImportFile != null && model.ImportFile.InputStream.Length > 0)
			{
				try
				{
					var result = await this.ImportData(model.ImportFile.InputStream);

					if (!string.IsNullOrEmpty(_importMessage))
					{
						return JsonCamelCase(Utility.CreateFailJsonResult(_importMessage),
								JsonRequestBehavior.AllowGet, true);
					}
					else
					{
						return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessImport),
								JsonRequestBehavior.AllowGet, true);
					}
				}
				catch (Exception)
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgFileError),
							JsonRequestBehavior.AllowGet, true);
				}
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgInvalidFile),
					JsonRequestBehavior.AllowGet, true);
			}
		}

		private async Task<int> ImportData(Stream stream)
		{
			XSSFWorkbook workbook;
			workbook = new XSSFWorkbook(stream);

			ISheet sheet = workbook.GetSheetAt(0);
			int rowIndex = 0;
			int recordCount = 0;

			while (true)
			{
				var tmpMsg = string.Empty;
				try
				{
					rowIndex++;
					IRow row = sheet.GetRow(rowIndex);
					if (row == null)
					{
						break;
					}

					var model = new InvoiceModel();
					int columnIndex = 0;

					// 发票抬头
					if (row.GetCell(columnIndex) != null)
					{
						model.InvoiceTitle = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (string.IsNullOrEmpty(model.InvoiceTitle))
						{
							tmpMsg += string.Format(Resources.MsgImportNotExist, model.InvoiceTitle, Resources.InvoiceTitle) + "<br/>";
						}
						else if (model.InvoiceTitle.Length > 100)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.InvoiceTitle, Resources.InvoiceTitle, 100) + "<br/>";
						}
					}

					// 税号
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						model.TaxNum = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (model.TaxNum.Length > 100)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.InvoiceTitle, Resources.TaxNum, 100) + "<br/>";
						}
					}

					// 地址及电话
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						model.AddressAndTel = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (model.AddressAndTel.Length > 200)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.InvoiceTitle, Resources.AddressAndTel, 200) + "<br/>";
						}
					}

					// 开户行
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						model.Bank = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (model.Bank.Length > 100)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.InvoiceTitle, Resources.Bank, 100) + "<br/>";
						}
					}

					// 账号
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						model.BankAccount = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (model.BankAccount.Length > 100)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.InvoiceTitle, Resources.BankAccount, 100) + "<br/>";
						}
					}

					var exist = await DbContext.InvoiceMaster.AsNoTracking()
							.AnyAsync(x => x.Status == ConstValues.Status.正常 && x.InvoiceTitle == model.InvoiceTitle && x.TaxNum == model.TaxNum);

					if (exist)
					{
						tmpMsg += string.Format(Resources.MsgImportIsExist, model.InvoiceTitle, Resources.InvoiceTitle) + "<br/>";
					}

					if (!string.IsNullOrEmpty(tmpMsg))
					{
						_importMessage += tmpMsg;
						continue;
					}

					var invoiceMaster = new InvoiceMaster
					{
						ID = Utility.GetTableId(ConstValues.TableName.InvoiceMaster),
						InvoiceTitle = model.InvoiceTitle?.Trim(),
						TaxNum = !string.IsNullOrWhiteSpace(model.TaxNum) ? model.TaxNum?.Trim() : ConstValues.DefaultInvoice,
						AddressAndTel = model.AddressAndTel?.Trim(),
						Bank = model.Bank?.Trim(),
						BankAccount = model.BankAccount?.Trim(),
						Status = ConstValues.Status.正常,
						Sort = ConstValues.DefaultSort,
						Creator = LoginUser.UserName,
						CreateIP = LoginUser.IP,
						CreateDate = DateTime.Now,
					};
					DbContext.InvoiceMaster.Add(invoiceMaster);

					await DbContext.SaveChangesAsync();

					recordCount++;
				}
				catch (Exception)
				{
					continue;
				}
			}

			return await Task.FromResult(recordCount);
		}
	}
}